package com.api.common.alert.notififer;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.api.common.alert.model.AlertMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 钉钉机器人 告警提醒
 */
@Component
@Slf4j
@ConditionalOnProperty(prefix = "alert.dingtalk",name = "enabled",havingValue = "true")
public class DingTalkRobotNotifier implements Notifier{

    //钉钉机器人 webhook 地址
    @Value("${alert.dingtalk.webhook}")
    private  String webhookUrl;

    @Value("${alert.dingtalk.enabled:false}")
    private boolean enabled;

    @Value("${alert.dingtalk.secret}")
    private  String secret;

    // 是否@所有人（紧急告警）
    @Value("${alert.dingtalk.at-all:false}")
    private boolean atAll;

    // @指定人的手机号列表（逗号分隔）
    @Value("${alert.dingtalk.at-mobiles:}")
    private String atMobiles;

    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Override
    public String getChannel() {
        return "dingtalk";
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public void send(AlertMessage event) {
        if(!this.enabled){
            log.debug("未启用钉钉告警");
            return;
        }

        // 构建美化的Markdown消息
        String markdownText = buildMarkdownMessage(event);

        // 构造请求体
        Map<String, Object> msg = new HashMap<>();
        msg.put("msgtype", "markdown");

        // Markdown内容
        Map<String, String> markdown = new HashMap<>();
        markdown.put("title", getAlertTitle(event));
        markdown.put("text", markdownText);
        msg.put("markdown", markdown);

        // @人配置
        Map<String, Object> at = buildAtConfig(event);
        msg.put("at", at);

        // 计算签名（如果配置了secret）
        String finalUrl = buildSignedUrl();

        try(HttpResponse response = HttpRequest.post(finalUrl)
                .header("Content-Type", "application/json")
                .timeout(10000)
                .body(JSONUtil.toJsonStr(msg))
                .execute()) {
            if(response.isOk()){
                String body = response.body();
                log.info("钉钉告警发送成功 | 类型={}, 响应={}", event.getAlertType(), body);
            } else {
                log.error("钉钉告警发送失败 | 状态码={}, 响应={}", response.getStatus(), response.body());
            }
        }catch (Exception e){
            log.error("钉钉告警发送失败 | 类型={}, 原因={}", event.getAlertType(), e.getMessage(), e);
        }
    }

    /**
     * 构建Markdown格式的告警消息
     */
    private String buildMarkdownMessage(AlertMessage event) {
        StringBuilder md = new StringBuilder();

        // 标题行（带emoji和颜色）
        md.append("### ").append(event.getLevel().getIcon()).append(" ")
                .append("【").append(event.getLevel().getName()).append("告警】")
                .append(getAlertTypeName(event.getAlertType()))
                .append("\n\n");

        // 基本信息
        md.append("---\n\n");
        md.append("**📌 告警信息**\n\n");
        md.append("- **级别：** ").append(event.getLevel().getName()).append("\n");
        md.append("- **类型：** ").append(getAlertTypeName(event.getAlertType())).append("\n");
        md.append("- **来源：** ").append(event.getSource()).append("\n");
        md.append("- **时间：** ").append(event.getTimestamp().format(TIME_FORMATTER)).append("\n");

        // 告警详情
        md.append("\n**📝 详细信息**\n\n");
        md.append("> ").append(event.getMessage()).append("\n");

        // 上下文信息（如果有）
        if (event.getContext() != null && !event.getContext().isEmpty()) {
            md.append("\n**🔍 上下文数据**\n\n");
            event.getContext().forEach((key, value) ->
                    md.append("- **").append(formatContextKey(key)).append("：** ").append(value).append("\n")
            );
        }

        // TraceId（便于日志追踪）
        if (StrUtil.isNotBlank(event.getTraceId())) {
            md.append("\n**🔗 追踪ID：** `").append(event.getTraceId()).append("`\n");
        }

        // 底部分隔线
        md.append("\n---\n");
        md.append("\n> 💡 请及时处理告警，保障系统稳定运行");

        return md.toString();
    }

    /**
     * 获取告警标题
     */
    private String getAlertTitle(AlertMessage event) {
        return String.format("%s [%s] %s",
                event.getLevel().getIcon(),
                event.getLevel().getName(),
                getAlertTypeName(event.getAlertType()));
    }

    /**
     * 获取告警类型的中文名称
     */
    private String getAlertTypeName(String alertType) {
        Map<String, String> typeNames = new HashMap<>();
        
        // API相关
        typeNames.put("API_FAILURE", "API调用失败");
        typeNames.put("API_SLOW", "API响应缓慢");
        typeNames.put("API_TIMEOUT", "API请求超时");
        typeNames.put("API_RATE_LIMIT", "API触发限流");
        
        // 任务相关
        typeNames.put("TASK_FAILURE", "任务执行失败");
        typeNames.put("TASK_TIMEOUT", "任务执行超时");
        typeNames.put("TASK_SKIPPED", "任务被跳过");
        typeNames.put("TASK_ADD_FAILURE", "任务添加失败");
        typeNames.put("TASK_REMOVE_FAILURE", "任务移除失败");
        typeNames.put("TASK_PAUSE_FAILURE", "任务暂停失败");
        
        // 线程池相关
        typeNames.put("THREADPOOL_SATURATED", "线程池饱和");
        typeNames.put("THREADPOOL_QUEUE_FULL", "线程池队列积压");
        typeNames.put("THREADPOOL_REJECTED", "线程池任务拒绝");
        
        // 数据库相关
        typeNames.put("DATABASE_CONNECTION_FAILURE", "数据库连接失败");
        typeNames.put("DATABASE_SLOW_QUERY", "数据库慢查询");
        typeNames.put("DATABASE_DEADLOCK", "数据库死锁");
        typeNames.put("DATABASE_POOL_EXHAUSTED", "数据库连接池耗尽");
        typeNames.put("DATABASE_VACUUM_FAILURE", "数据库优化失败");
        
        // Redis缓存相关
        typeNames.put("CACHE_HIT_RATE_LOW", "缓存命中率低");
        typeNames.put("CACHE_CONNECTION_FAILURE", "Redis连接失败");
        typeNames.put("CACHE_EVICTION_HIGH", "缓存驱逐率高");
        typeNames.put("CACHE_MEMORY_HIGH", "Redis内存使用率高");
        
        // MQ相关
        typeNames.put("MQ_SEND_FAILURE", "消息发送失败");
        typeNames.put("MQ_CONSUME_FAILURE", "消息消费失败");
        typeNames.put("MQ_QUEUE_BACKLOG", "队列消息积压");
        typeNames.put("MQ_DEAD_LETTER", "消息进入死信队列");
        
        // Elasticsearch相关
        typeNames.put("ES_CONNECTION_FAILURE", "ES连接失败");
        typeNames.put("ES_QUERY_SLOW", "ES查询慢");
        typeNames.put("ES_INDEX_FAILURE", "ES索引失败");
        typeNames.put("ES_SYNC_DELAY", "ES数据同步延迟");
        
        // 推荐系统相关
        typeNames.put("RECOMMEND_MODEL_REBUILD_FAILURE", "推荐模型重建失败");
        typeNames.put("RECOMMEND_MODEL_SLOW", "推荐模型重建耗时长");
        typeNames.put("RECOMMEND_DATA_INSUFFICIENT", "推荐数据不足");
        typeNames.put("RECOMMEND_COLD_START", "用户冷启动");
        
        // 风控相关
        typeNames.put("RISK_MODEL_FAILURE", "风控模型失败");
        typeNames.put("RISK_HIGH_SCORE", "检测到高风险行为");
        typeNames.put("RISK_BLOCK_RATE_HIGH", "风控拦截率过高");
        typeNames.put("RISK_FEATURE_EXTRACTION_FAILURE", "风控特征提取失败");
        
        // 网关相关
        typeNames.put("GATEWAY_ROUTE_FAILURE", "网关路由失败");
        typeNames.put("GATEWAY_CIRCUIT_BREAKER_OPEN", "熔断器已打开");
        typeNames.put("GATEWAY_UPSTREAM_UNAVAILABLE", "上游服务不可用");
        
        // 限流相关
        typeNames.put("RATE_LIMIT_TRIGGERED", "触发限流");
        typeNames.put("RATE_LIMIT_BURST", "检测到突发流量");
        
        // 数据同步相关
        typeNames.put("CANAL_SYNC_FAILURE", "Canal同步失败");
        typeNames.put("CANAL_CONNECTION_LOST", "Canal连接丢失");
        typeNames.put("DATA_INCONSISTENCY", "数据不一致");
        
        // 系统资源相关
        typeNames.put("MEMORY_HIGH", "内存使用率高");
        typeNames.put("CPU_HIGH", "CPU使用率高");
        typeNames.put("DISK_SPACE_LOW", "磁盘空间不足");
        typeNames.put("FILE_DESCRIPTOR_HIGH", "文件描述符使用率高");
        
        // 业务相关
        typeNames.put("CLEANUP_FAILURE", "数据清理失败");
        typeNames.put("AGGREGATION_FAILURE", "统计聚合失败");
        typeNames.put("ARCHIVE_FAILURE", "数据归档失败");
        typeNames.put("CONFIG_RELOAD_FAILURE", "配置重载失败");
        typeNames.put("CONFIG_WATCH_START_FAILURE", "配置监听启动失败");
        
        // 用户业务相关
        typeNames.put("USER_LOGIN_FAILURE", "用户登录失败");
        typeNames.put("USER_REGISTER_FAILURE", "用户注册失败");
        typeNames.put("USER_ACCOUNT_LOCKED", "用户账户被锁定");
        typeNames.put("USER_ABNORMAL_BEHAVIOR", "用户异常行为");
        typeNames.put("USER_ACTIVE_DROP", "用户活跃度下降");
        
        // 接口调用业务相关
        typeNames.put("INTERFACE_QUOTA_EXHAUSTED", "接口调用次数耗尽");
        typeNames.put("INTERFACE_OFFLINE", "接口已下线");
        typeNames.put("INTERFACE_PERMISSION_DENIED", "接口权限不足");
        typeNames.put("INTERFACE_CALL_SPIKE", "接口调用激增");
        typeNames.put("INTERFACE_ERROR_RATE_HIGH", "接口错误率高");
        
        // 支付订单业务相关
        typeNames.put("PAYMENT_FAILURE", "支付失败");
        typeNames.put("PAYMENT_TIMEOUT", "支付超时");
        typeNames.put("ORDER_CREATION_FAILURE", "订单创建失败");
        typeNames.put("ORDER_CANCEL_RATE_HIGH", "订单取消率高");
        typeNames.put("REFUND_FAILURE", "退款失败");
        
        // 数据验证业务相关
        typeNames.put("DATA_VALIDATION_FAILURE", "数据校验失败");
        typeNames.put("DATA_FORMAT_ERROR", "数据格式错误");
        typeNames.put("DATA_DUPLICATION", "数据重复");
        typeNames.put("ILLEGAL_PARAMETER", "非法参数");
        
        // 第三方服务相关
        typeNames.put("THIRD_PARTY_API_FAILURE", "第三方API失败");
        typeNames.put("THIRD_PARTY_TIMEOUT", "第三方服务超时");
        typeNames.put("THIRD_PARTY_RATE_LIMITED", "第三方服务限流");
        typeNames.put("SMS_SEND_FAILURE", "短信发送失败");
        typeNames.put("EMAIL_SEND_FAILURE", "邮件发送失败");
        
        // 审计安全相关
        typeNames.put("SENSITIVE_OPERATION", "敏感操作");
        typeNames.put("UNAUTHORIZED_ACCESS", "未授权访问");
        typeNames.put("SUSPICIOUS_IP", "可疑IP");
        typeNames.put("DATA_EXPORT_LARGE", "大量数据导出");
        
        // 业务指标异常
        typeNames.put("METRIC_ANOMALY", "业务指标异常");
        typeNames.put("CONVERSION_RATE_DROP", "转化率下降");
        typeNames.put("SUCCESS_RATE_DROP", "成功率下降");
        typeNames.put("TRAFFIC_ANOMALY", "流量异常");
        
        // 其他
        typeNames.put("CLASSIFIER_FAILURE", "分类器失败");

        return typeNames.getOrDefault(alertType, alertType);
    }

    /**
     * 格式化上下文key的显示名称
     */
    private String formatContextKey(String key) {
        Map<String, String> keyNames = new HashMap<>();
        
        // 通用
        keyNames.put("reason", "失败原因");
        keyNames.put("failCount", "失败次数");
        keyNames.put("retryCount", "重试次数");
        keyNames.put("durationMs", "耗时(ms)");
        keyNames.put("timeoutMs", "超时阈值(ms)");
        keyNames.put("requestCount", "请求数");
        keyNames.put("threshold", "阈值");
        keyNames.put("service", "服务");
        keyNames.put("env", "环境");
        
        // API相关
        keyNames.put("apiName", "接口名称");
        keyNames.put("userId", "用户ID");
        keyNames.put("username", "用户名");
        keyNames.put("interfaceId", "接口ID");
        keyNames.put("interfaceName", "接口名称");
        
        // 线程池相关
        keyNames.put("activeCount", "活跃线程数");
        keyNames.put("maxPoolSize", "最大线程数");
        keyNames.put("poolSize", "线程池大小");
        keyNames.put("queueSize", "队列大小");
        keyNames.put("queueCapacity", "队列容量");
        keyNames.put("rejectedCount", "拒绝数");
        
        // 数据库相关
        keyNames.put("datasource", "数据源");
        keyNames.put("sql", "SQL语句");
        keyNames.put("table", "表名");
        keyNames.put("database", "数据库");
        keyNames.put("lockInfo", "锁信息");
        keyNames.put("activeConnections", "活跃连接数");
        keyNames.put("maxConnections", "最大连接数");
        
        // 缓存相关
        keyNames.put("hitRate", "命中率");
        keyNames.put("evictionCount", "驱逐数");
        keyNames.put("totalCount", "总数");
        keyNames.put("usedMemoryMb", "已用内存(MB)");
        keyNames.put("maxMemoryMb", "最大内存(MB)");
        keyNames.put("host", "主机");
        
        // MQ相关
        keyNames.put("exchange", "交换机");
        keyNames.put("routingKey", "路由键");
        keyNames.put("queue", "队列");
        keyNames.put("messageId", "消息ID");
        keyNames.put("messageCount", "消息数量");
        keyNames.put("originalQueue", "原队列");
        
        // ES相关
        keyNames.put("cluster", "集群");
        keyNames.put("nodes", "节点");
        keyNames.put("index", "索引");
        keyNames.put("docId", "文档ID");
        keyNames.put("query", "查询语句");
        keyNames.put("delayMinutes", "延迟(分钟)");
        
        // 推荐系统相关
        keyNames.put("modelType", "模型类型");
        keyNames.put("interfaceCount", "接口数");
        keyNames.put("actualCount", "实际数量");
        keyNames.put("requiredCount", "需要数量");
        
        // 风控相关
        keyNames.put("modelName", "模型名称");
        keyNames.put("riskScore", "风险分");
        keyNames.put("blockRate", "拦截率");
        keyNames.put("totalRequests", "总请求数");
        keyNames.put("blockedRequests", "拦截数");
        keyNames.put("ip", "IP地址");
        
        // 网关相关
        keyNames.put("routeId", "路由ID");
        keyNames.put("targetUri", "目标URI");
        keyNames.put("serviceName", "服务名");
        keyNames.put("failureRate", "失败率");
        keyNames.put("instances", "实例列表");
        
        // 限流相关
        keyNames.put("resource", "资源");
        keyNames.put("limit", "限制");
        keyNames.put("currentQps", "当前QPS");
        keyNames.put("normalQps", "正常QPS");
        
        // 数据同步相关
        keyNames.put("destination", "目标实例");
        keyNames.put("sourceId", "源ID");
        keyNames.put("targetId", "目标ID");
        keyNames.put("detail", "详细信息");
        
        // 系统资源相关
        keyNames.put("cpuUsage", "CPU使用率");
        keyNames.put("usageRate", "使用率");
        keyNames.put("partition", "分区");
        keyNames.put("availableMb", "可用空间(MB)");
        keyNames.put("totalMb", "总空间(MB)");
        
        // 业务相关
        keyNames.put("dataType", "数据类型");
        keyNames.put("aggregationType", "聚合类型");
        keyNames.put("period", "周期");
        keyNames.put("configName", "配置名称");
        keyNames.put("exception", "异常类型");
        keyNames.put("message", "消息");
        keyNames.put("stackTrace", "堆栈信息");
        
        // 用户业务相关
        keyNames.put("behavior", "行为");
        keyNames.put("activeUsers", "活跃用户数");
        keyNames.put("previousUsers", "之前用户数");
        
        // 订单支付相关
        keyNames.put("orderId", "订单号");
        keyNames.put("amount", "金额");
        keyNames.put("productName", "商品名称");
        keyNames.put("totalOrders", "总订单数");
        keyNames.put("canceledOrders", "取消订单数");
        keyNames.put("cancelRate", "取消率");
        
        // 数据验证相关
        keyNames.put("fieldName", "字段名");
        keyNames.put("value", "值");
        keyNames.put("rule", "规则");
        keyNames.put("expectedFormat", "期望格式");
        keyNames.put("actualFormat", "实际格式");
        keyNames.put("paramName", "参数名");
        keyNames.put("paramValue", "参数值");
        keyNames.put("method", "方法");
        
        // 第三方服务相关
        keyNames.put("phone", "手机号");
        keyNames.put("email", "邮箱");
        
        // 审计安全相关
        keyNames.put("operation", "操作");
        keyNames.put("target", "目标");
        keyNames.put("resource", "资源");
        
        // 业务指标相关
        keyNames.put("metricName", "指标名称");
        keyNames.put("currentValue", "当前值");
        keyNames.put("expectedValue", "期望值");
        keyNames.put("deviation", "偏差");
        keyNames.put("conversionType", "转化类型");
        keyNames.put("currentRate", "当前率");
        keyNames.put("previousRate", "之前率");
        keyNames.put("dropRate", "下降率");
        keyNames.put("businessType", "业务类型");
        keyNames.put("trafficType", "流量类型");
        keyNames.put("normalValue", "正常值");
        keyNames.put("trend", "趋势");
        keyNames.put("totalCalls", "总调用数");
        keyNames.put("errorCalls", "错误调用数");
        keyNames.put("errorRate", "错误率");
        keyNames.put("currentQps", "当前QPS");
        keyNames.put("normalQps", "正常QPS");
        keyNames.put("recordCount", "记录数");

        return keyNames.getOrDefault(key, key);
    }

    /**
     * 构建@人配置
     */
    private Map<String, Object> buildAtConfig(AlertMessage event) {
        Map<String, Object> at = new HashMap<>();

        // 紧急告警时@所有人
        boolean shouldAtAll = this.atAll || "CRITICAL".equals(event.getLevel().name());
        at.put("isAtAll", shouldAtAll);

        // @指定人
        List<String> atMobilesList = new ArrayList<>();
        if (StrUtil.isNotBlank(atMobiles)) {
            atMobilesList = Arrays.stream(atMobiles.split(","))
                    .map(String::trim)
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toList());
        }
        at.put("atMobiles", atMobilesList);

        return at;
    }

    /**
     * 构建带签名的URL（如果配置了secret）
     */
    private String buildSignedUrl() {
        if (StrUtil.isBlank(secret)) {
            return webhookUrl;
        }

        try {
            long timestamp = System.currentTimeMillis();
            String stringToSign = timestamp + "\n" + secret;
            String sign = SecureUtil.hmacSha256(secret).digestBase64(stringToSign, false);
            String encodedSign = URLEncoder.encode(sign, "UTF-8");

            return webhookUrl + "&timestamp=" + timestamp + "&sign=" + encodedSign;
        } catch (Exception e) {
            log.error("生成钉钉签名失败", e);
            return webhookUrl;
        }
    }
}
